import copy
import random
from collections import Iterator
from Individual import *
from encode import *

modeNum = 3


def crossover(pop, pc, actList, resources):
    """
    交叉
    :param pop:
    :param pc:
    :param actList:
    :param resources:
    :return:
    """
    pop_size = len(pop)
    chrom_length = len(pop[0].actStr)
    for i in range(0, pop_size - 1):
        if random.random() < pc:
            # 活动列表交叉
            atemp1 = []
            atemp2 = []
            p = pop[i].copy()
            q = copy.deepcopy(pop[i + 1])
            p_mother = p.actStr
            q_father = q.actStr
            n1 = random.randint(1, chrom_length - 2)  # 交叉位点
            n2 = random.randint(n1, chrom_length - 1)  # 交叉位点
            atemp1.extend(p_mother[0: n1])
            atemp2.extend(q_father[0: n1])
            # 确定child中n1-n2位基因
            k = 0
            while k < (n2 - n1):
                for item in q_father:
                    if item not in atemp1:
                        atemp1.append(item)
                        break
                for item in p_mother:
                    if item not in atemp2:
                        atemp2.append(item)
                        break
                k += 1
            # 确定child中n2-n位基因
            j = 0
            while j < (chrom_length - n2):
                for item in p_mother:
                    if item not in atemp1:
                        atemp1.append(item)
                        break
                for item in q_father:
                    if item not in atemp2:
                        atemp2.append(item)
                        break
                j += 1
            # 模式列交叉
            n3 = random.randint(1, modeNum + 1)
            p_mother = p.modeStr
            q_father = q.modeStr
            mtemp1 = p_mother[0: n3]
            mtemp2 = q_father[0: n3]
            mtemp1.extend(q_father[n3: chrom_length])
            mtemp2.extend(p_mother[n3: chrom_length])
            # 序列合法性校正
            atemp1 = fixActOrder(atemp1, actList)
            atemp2 = fixActOrder(atemp2, actList)
            mtemp1 = fixModeOrder(mtemp1, atemp1, actList, pop[i].resources)
            mtemp2 = fixModeOrder(mtemp2, atemp2, actList, pop[i + 1].resources)
            # print("***********************")
            # print(atemp1)
            # print(atemp2)
            # print(mtemp1)
            # print(mtemp2)
            # print("***********************")
            pop[i].actStr = atemp1
            pop[i].modeStr = mtemp1
            pop[i + 1].actStr = atemp2
            pop[i + 1].modeStr = mtemp2
    return pop.copy()


if __name__ == '__main__':
    pop = [[[2, 4, 1, 6, 3, 5], [1, 3, 5, 2, 4, 6]], [[0, 0, 0, 1, 0, 1], [1, 0, 1, 1, 1, 0]]]
    crossoverpro = 0.8
    p1 = crossover(pop, crossoverpro)
    print(p1)
